home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue49 / Alfresco / AALnkLst.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-07-25  |  18.8 KB  |  763 lines

  1. {*********************************************************}
  2. {* AALnkLst                                              *}
  3. {* Copyright (c) Julian M Bucknall 1998-1999             *}
  4. {* All rights reserved.                                  *}
  5. {*********************************************************}
  6. {* Algorithms Alfresco linked lists, stacks and queues   *}
  7. {*********************************************************}
  8.  
  9. {Note: this unit is released as freeware. In other words, you are free
  10.        to use this unit in your own applications, however I retain all
  11.        copyright to the code. JMB}
  12.  
  13. unit AALnkLst;
  14.  
  15. interface
  16.  
  17. uses
  18.   SysUtils;
  19.  
  20. {$IFOPT D+}
  21. {$DEFINE InDebugMode}
  22. {$ENDIF}
  23.  
  24. {$DEFINE UseNodeManager}
  25.  
  26. const
  27.   PageNodeCount = 30;
  28.  
  29. type
  30.   TaaCompareFunction = function (aItem1, aItem2 : pointer) : integer;
  31.  
  32. type
  33.   PsllNode = ^TsllNode;
  34.   TsllNode = packed record
  35.     sllnNext : PsllNode;
  36.     sllnData : pointer;
  37.   end;
  38.  
  39.   TaaSingleList = class
  40.     private
  41.       FCount    : integer;
  42.       FCursor   : PsllNode;
  43.       FHead     : PsllNode;
  44.     protected
  45.     public
  46.       constructor Create;
  47.       destructor Destroy; override;
  48.  
  49.       procedure InsertAfter(aItem : pointer);
  50.       function DeleteAfter : pointer;
  51.  
  52.       function IsBeforeFirst : boolean;
  53.       function IsLast : boolean;
  54.       procedure MoveBeforeFirst;
  55.       function MoveNext : boolean;
  56.  
  57.       procedure Clear;
  58.       function Examine : pointer;
  59.       procedure Sort(aCompare : TaaCompareFunction);
  60.  
  61.       property Count : integer read FCount;
  62.   end;
  63.  
  64. type
  65.   PdllNode = ^TdllNode;
  66.   TdllNode = packed record
  67.     dllnNext : PdllNode;
  68.     dllnPrev : PdllNode;
  69.     dllnData : pointer;
  70.   end;
  71.  
  72.   TaaDoubleList = class
  73.     private
  74.       FCount    : integer;
  75.       FCursor   : PdllNode;
  76.       FHead     : PdllNode;
  77.       FTail     : PdllNode;
  78.     protected
  79.     public
  80.       constructor Create;
  81.       destructor Destroy; override;
  82.  
  83.       procedure InsertBefore(aItem : pointer);
  84.       procedure InsertAfter(aItem : pointer);
  85.       function Delete : pointer;
  86.  
  87.       function IsAfterLast : boolean;
  88.       function IsBeforeFirst : boolean;
  89.       procedure MoveAfterLast;
  90.       procedure MoveBeforeFirst;
  91.       function MoveNext : boolean;
  92.       function MovePrevious : boolean;
  93.  
  94.       procedure Clear;
  95.       function Examine : pointer;
  96.       procedure Sort(aCompare : TaaCompareFunction);
  97.  
  98.       property Count : integer read FCount;
  99.   end;
  100.  
  101.  
  102. type
  103.   TaaStack = class
  104.     private
  105.       FCount : integer;
  106.       FHead  : PsllNode;
  107.     protected
  108.     public
  109.       constructor Create;
  110.       destructor Destroy; override;
  111.  
  112.       procedure Clear;
  113.       function Examine : pointer;
  114.       function IsEmpty : boolean;
  115.       function Pop : pointer;
  116.       procedure Push(aItem : pointer);
  117.  
  118.       property Count : integer read FCount;
  119.   end;
  120.  
  121. type
  122.   TaaQueue = class
  123.     private
  124.       FCount : integer;
  125.       FHead  : PsllNode;
  126.       FTail  : PsllNode;
  127.     protected
  128.     public
  129.       constructor Create;
  130.       destructor Destroy; override;
  131.  
  132.       procedure Clear;
  133.       function Dequeue : pointer;
  134.       procedure Enqueue(aItem : pointer);
  135.       function Examine : pointer;
  136.       function IsEmpty : boolean;
  137.  
  138.       property Count : integer read FCount;
  139.   end;
  140.  
  141.  
  142. implementation
  143.  
  144. {===SingleNodeManager================================================}
  145. type
  146.   PsnmPage = ^TsnmPage;
  147.   TsnmPage = packed record
  148.     snmpNext  : PsnmPage;
  149.     snmpNodes : array [0..pred(PageNodeCount)] of TsllNode;
  150.   end;
  151. {--------}
  152. var
  153.   snmFreeList : PsllNode;
  154.   snmPageList : PsnmPage;
  155. {--------}
  156. procedure snmFreeNode(aNode : PsllNode);
  157. begin
  158.   {$IFDEF UseNodeManager}
  159.   {add the node to the top of the free list}
  160.   aNode^.sllnNext := snmFreeList;
  161.   snmFreeList := aNode;
  162.   {$ELSE}
  163.   Dispose(aNode);
  164.   {$ENDIF}
  165. end;
  166. {--------}
  167. procedure snmAllocPage;
  168. var
  169.   NewPage : PsnmPage;
  170.   i       : integer;
  171. begin
  172.   {get a new page}
  173.   New(NewPage);
  174.   {add it to the current list of pages}
  175.   NewPage^.snmpNext := snmPageList;
  176.   snmPageList := NewPage;
  177.   {add all the nodes on the page to the free list}
  178.   for i := 0 to pred(PageNodeCount) do
  179.     snmFreeNode(@NewPage^.snmpNodes[i]);
  180. end;
  181. {--------}
  182. function snmAllocNode : PsllNode;
  183. begin
  184.   {$IFDEF UseNodeManager}
  185.   {if the free list is empty, allocate a new page of nodes}
  186.   if (snmFreeList = nil) then
  187.     snmAllocPage;
  188.   {return the first node on the free list}
  189.   Result := snmFreeList;
  190.   snmFreeList := Result^.sllnNext;
  191.   {$ELSE}
  192.   New(Result);
  193.   {$ENDIF}
  194.   {$IFDEF InDebugMode}
  195.   Result^.sllnNext := nil;
  196.   Result^.sllnData := nil;
  197.   {$ENDIF}
  198. end;
  199. {====================================================================}
  200.  
  201.  
  202. {===DoubleNodeManager================================================}
  203. type
  204.   PdnmPage = ^TdnmPage;
  205.   TdnmPage = packed record
  206.     dnmpNext  : PdnmPage;
  207.     dnmpNodes : array [0..pred(PageNodeCount)] of TdllNode;
  208.   end;
  209. {--------}
  210. var
  211.   dnmFreeList : PdllNode;
  212.   dnmPageList : PdnmPage;
  213. {--------}
  214. procedure dnmFreeNode(aNode : PdllNode);
  215. begin
  216.   {$IFDEF UseNodeManager}
  217.   {add the node to the top of the free list}
  218.   aNode^.dllnNext := dnmFreeList;
  219.   dnmFreeList := aNode;
  220.   {$ELSE}
  221.   Dispose(aNode);
  222.   {$ENDIF}
  223. end;
  224. {--------}
  225. procedure dnmAllocPage;
  226. var
  227.   NewPage : PdnmPage;
  228.   i       : integer;
  229. begin
  230.   {get a new page}
  231.   New(NewPage);
  232.   {add it to the current list of pages}
  233.   NewPage^.dnmpNext := dnmPageList;
  234.   dnmPageList := NewPage;
  235.   {add all the nodes on the page to the free list}
  236.   for i := 0 to pred(PageNodeCount) do
  237.     dnmFreeNode(@NewPage^.dnmpNodes[i]);
  238. end;
  239. {--------}
  240. function dnmAllocNode : PdllNode;
  241. begin
  242.   {$IFDEF UseNodeManager}
  243.   {if the free list is empty, allocate a new page of nodes}
  244.   if (dnmFreeList = nil) then
  245.     dnmAllocPage;
  246.   {return the first node on the free list}
  247.   Result := dnmFreeList;
  248.   dnmFreeList := Result^.dllnNext;
  249.   {$ELSE}
  250.   New(Result);
  251.   {$ENDIF}
  252.   {$IFDEF InDebugMode}
  253.   Result^.dllnNext := nil;
  254.   Result^.dllnData := nil;
  255.   {$ENDIF}
  256. end;
  257. {====================================================================}
  258.  
  259.  
  260. {===TaaSingleList====================================================}
  261. constructor TaaSingleList.Create;
  262. begin
  263.   inherited Create;
  264.   {allocate a head node}
  265.   FHead := snmAllocNode;
  266.   FHead^.sllnNext := nil;
  267.   FHead^.sllnData := nil;
  268.   {set the cursor to the head node}
  269.   FCursor := FHead;
  270. end;
  271. {--------}
  272. destructor TaaSingleList.Destroy;
  273. begin
  274.   Clear;
  275.   snmFreeNode(FHead);
  276.   inherited Destroy;
  277. end;
  278. {--------}
  279. procedure TaaSingleList.Clear;
  280. var
  281.   Temp : PsllNode;
  282. begin
  283.   Temp := FHead^.sllnNext;
  284.   while (Temp <> nil) do begin
  285.     FHead^.sllnNext := Temp^.sllnNext;
  286.     snmFreeNode(Temp);
  287.     Temp := FHead^.sllnNext;
  288.   end;
  289.   FCount := 0;
  290. end;
  291. {--------}
  292. function TaaSingleList.DeleteAfter : pointer;
  293. var
  294.   OldNode : PsllNode;
  295. begin
  296.   OldNode := FCursor^.sllnNext;
  297.   if (OldNode = nil) then
  298.     raise Exception.Create('TaaSingleList.DeleteAfter: cannot delete - at end of list');
  299.   Result := OldNode^.sllnData;
  300.   FCursor^.sllnNext := OldNode^.sllnNext;
  301.   snmFreeNode(OldNode);
  302.   dec(FCount);
  303. end;
  304. {--------}
  305. function TaaSingleList.Examine : pointer;
  306. begin
  307.   {return the data part of the cursor}
  308.   Result := FCursor^.sllnData;
  309. end;
  310. {--------}
  311. procedure TaaSingleList.InsertAfter(aItem : pointer);
  312. var
  313.   NewNode : PsllNode;
  314. begin
  315.   {allocate a new node and insert after the cursor}
  316.   NewNode := snmAllocNode;
  317.   NewNode^.sllnData := aItem;
  318.   NewNode^.sllnNext := FCursor^.sllnNext;
  319.   FCursor^.sllnNext := NewNode;
  320.   inc(FCount);
  321. end;
  322. {--------}
  323. function TaaSingleList.IsBeforeFirst : boolean;
  324. begin
  325.   Result := FCursor = FHead;
  326. end;
  327. {--------}
  328. function TaaSingleList.IsLast : boolean;
  329. begin
  330.   Result := FCursor^.sllnNext = nil;
  331. end;
  332. {--------}
  333. procedure TaaSingleList.MoveBeforeFirst;
  334. begin
  335.   {set the cursor to the head node}
  336.   FCursor := FHead;
  337. end;
  338. {--------}
  339. function TaaSingleList.MoveNext : boolean;
  340. begin
  341.   {advance the cursor to its own next pointer}
  342.   if (FCursor^.sllnNext = nil) then
  343.     Result := false
  344.   else begin
  345.     FCursor := FCursor^.sllnNext;
  346.     Result := true;
  347.   end;
  348. end;
  349. {--------}
  350. procedure TaaSingleList.Sort(aCompare : TaaCompareFunction);
  351. var
  352.   Walker : PsllNode;
  353.   Temp   : PsllNode;
  354.   WalkerParent : PsllNode;
  355.   TempParent   : PsllNode;
  356. begin
  357.   {if there are zero (or one) items the list is already sorted}
  358.   if (Count <= 1) then
  359.     Exit;
  360.   {perform an insertion sort from the second item onwards}
  361.   WalkerParent := FHead^.sllnNext;
  362.   Walker := WalkerParent^.sllnNext;
  363.   while (Walker <> nil) do begin
  364.     {find where the walker item should be in the sorted list to its
  365.      left - we walk the sorted sublist making a note of the parent as
  366.      we go so that we can insert properly. Note that the loop below
  367.      will terminate in the worst case by the walker node itself - we
  368.      won't run off the end of the list}
  369.     TempParent := FHead;
  370.     Temp := TempParent^.sllnNext;
  371.     while (aCompare(Temp^.sllnData, Walker^.sllnData) < 0) do begin
  372.       TempParent := Temp;
  373.       Temp := TempParent^.sllnNext;
  374.     end;
  375.     {did we find the walker node? If so, it's in the right place so
  376.      move the walker's parent on by one link}
  377.     if (Temp = Walker) then
  378.       WalkerParent := Walker
  379.     {otherwise, move the walker node into the correct place in the
  380.      sorted sublist; leave the walker's parent where it is}
  381.     else begin
  382.       {disconnect the walker node}
  383.       WalkerParent^.sllnNext := Walker^.sllnNext;
  384.       {connect the walker node in the correct place}
  385.       Walker^.sllnNext := Temp;
  386.       TempParent^.sllnNext := Walker;
  387.     end;
  388.     {set the walker node}
  389.     Walker := WalkerParent^.sllnNext;
  390.   end;
  391. end;
  392. {====================================================================}
  393.  
  394.  
  395. {===TaaDoubleList========================================================}
  396. constructor TaaDoubleList.Create;
  397. begin
  398.   inherited Create;
  399.   {allocate a head and a tail node}
  400.   FHead := dnmAllocNode;
  401.   FTail := dnmAllocNode;
  402.   FHead^.dllnNext := FTail;
  403.   FHead^.dllnPrev := nil;
  404.   FHead^.dllnData := nil;
  405.   FTail^.dllnNext := nil;
  406.   FTail^.dllnPrev := FHead;
  407.   FTail^.dllnData := nil;
  408.   {set the cursor to the head node}
  409.   FCursor := FHead;
  410. end;
  411. {--------}
  412. destructor TaaDoubleList.Destroy;
  413. begin
  414.   Clear;
  415.   dnmFreeNode(FHead);
  416.   dnmFreeNode(FTail);
  417.   inherited Destroy;
  418. end;
  419. {--------}
  420. procedure TaaDoubleList.Clear;
  421. var
  422.   Temp : PdllNode;
  423. begin
  424.   Temp := FHead^.dllnNext;
  425.   while (Temp <> FTail) do begin
  426.     FHead^.dllnNext := Temp^.dllnNext;
  427.     dnmFreeNode(Temp);
  428.     Temp := FHead^.dllnNext;
  429.   end;
  430.   FCount := 0;
  431. end;
  432. {--------}
  433. function TaaDoubleList.Delete : pointer;
  434. var
  435.   OldNode : PdllNode;
  436. begin
  437.   OldNode := FCursor;
  438.   if (OldNode = FHead) or (OldNode = FTail) then
  439.     raise Exception.Create('TaaDoubleList.Delete: cannot delete - at start/end of list');
  440.   Result := OldNode^.dllnData;
  441.   OldNode^.dllnPrev^.dllnNext := OldNode^.dllnNext;
  442.   OldNode^.dllnNext^.dllnPrev := OldNode^.dllnPrev;
  443.   FCursor := OldNode^.dllnNext;
  444.   dnmFreeNode(OldNode);
  445.   dec(FCount);
  446. end;
  447. {--------}
  448. function TaaDoubleList.Examine : pointer;
  449. begin
  450.   {return the data part of the cursor}
  451.   Result := FCursor^.dllnData;
  452. end;
  453. {--------}
  454. procedure TaaDoubleList.InsertAfter(aItem : pointer);
  455. var
  456.   NewNode : PdllNode;
  457. begin
  458.   if (FCursor = FTail) then
  459.     FCursor := FCursor^.dllnPrev;
  460.   {allocate a new node and insert after the cursor}
  461.   NewNode := dnmAllocNode;
  462.   NewNode^.dllnData := aItem;
  463.   NewNode^.dllnNext := FCursor^.dllnNext;
  464.   NewNode^.dllnPrev := FCursor;
  465.   FCursor^.dllnNext := NewNode;
  466.   NewNode^.dllnNext^.dllnPrev := NewNode;
  467.   inc(FCount);
  468. end;
  469. {--------}
  470. procedure TaaDoubleList.InsertBefore(aItem : pointer);
  471. var
  472.   NewNode : PdllNode;
  473. begin
  474.   if (FCursor = FHead) then
  475.     FCursor := FCursor^.dllnNext;
  476.   {allocate a new node and insert before the cursor}
  477.   NewNode := dnmAllocNode;
  478.   NewNode^.dllnData := aItem;
  479.   NewNode^.dllnNext := FCursor;
  480.   NewNode^.dllnPrev := FCursor^.dllnPrev;
  481.   NewNode^.dllnPrev^.dllnNext := NewNode;
  482.   FCursor^.dllnPrev := NewNode;
  483.   inc(FCount);
  484. end;
  485. {--------}
  486. function TaaDoubleList.IsAfterLast : boolean;
  487. begin
  488.   Result := FCursor = FTail;
  489. end;
  490. {--------}
  491. function TaaDoubleList.IsBeforeFirst : boolean;
  492. begin
  493.   Result := FCursor = FHead;
  494. end;
  495. {--------}
  496. procedure TaaDoubleList.MoveAfterLast;
  497. begin
  498.   {set the cursor to the tail node}
  499.   FCursor := FTail;
  500. end;
  501. {--------}
  502. procedure TaaDoubleList.MoveBeforeFirst;
  503. begin
  504.   {set the cursor to the head node}
  505.   FCursor := FHead;
  506. end;
  507. {--------}
  508. function TaaDoubleList.MoveNext : boolean;
  509. begin
  510.   {advance the cursor to its own next pointer}
  511.   if (FCursor = FTail) then
  512.     Result := false
  513.   else begin
  514.     FCursor := FCursor^.dllnNext;
  515.     Result := true;
  516.   end;
  517. end;
  518. {--------}
  519. function TaaDoubleList.MovePrevious : boolean;
  520. begin
  521.   {retard the cursor to its own previous pointer}
  522.   if (FCursor = FHead) then
  523.     Result := false
  524.   else begin
  525.     FCursor := FCursor^.dllnPrev;
  526.     Result := true;
  527.   end;
  528. end;
  529. {--------}
  530. procedure TaaDoubleList.Sort(aCompare : TaaCompareFunction);
  531. var
  532.   Walker : PdllNode;
  533.   Temp   : PdllNode;
  534.   WalkerParent : PdllNode;
  535.   TempParent   : PdllNode;
  536. begin
  537.   {if there are zero (or one) items the list is already sorted}
  538.   if (Count <= 1) then
  539.     Exit;
  540.   {perform an insertion sort from the second item onwards}
  541.   WalkerParent := FHead^.dllnNext;
  542.   Walker := WalkerParent^.dllnNext;
  543.   while (Walker <> FTail) do begin
  544.     {find where the walker item should be in the sorted list to its
  545.      left - we walk the sorted sublist making a note of the parent as
  546.      we go so that we can insert properly. Note that the loop below
  547.      will terminate in the worst case by the walker node itself - we
  548.      won't run off the end of the list}
  549.     TempParent := FHead;
  550.     Temp := TempParent^.dllnNext;
  551.     while (aCompare(Temp^.dllnData, Walker^.dllnData) < 0) do begin
  552.       TempParent := Temp;
  553.       Temp := TempParent^.dllnNext;
  554.     end;
  555.     {did we find the walker node? If so, move the walker's parent on
  556.      by one link}
  557.     if (Temp = Walker) then begin
  558.       WalkerParent := Walker;
  559.     end
  560.     {otherwise, move the walker node into the correct place in the
  561.      sorted sublist}
  562.     else begin
  563.       {disconnect the walker node}
  564.       WalkerParent^.dllnNext := Walker^.dllnNext;
  565.       {connect the walker node in the correct place}
  566.       Walker^.dllnNext := Temp;
  567.       TempParent^.dllnNext := Walker;
  568.     end;
  569.     {set the walker node}
  570.     Walker := WalkerParent^.dllnNext;
  571.   end;
  572.   {now patch up all of the previous links}
  573.   WalkerParent := FHead;
  574.   Walker := WalkerParent^.dllnNext;
  575.   while (WalkerParent <> FTail) do begin
  576.     Walker^.dllnPrev := WalkerParent;
  577.     WalkerParent := Walker;
  578.     Walker := WalkerParent^.dllnNext;
  579.   end;
  580. end;
  581. {====================================================================}
  582.  
  583.  
  584. {===TaaStack=========================================================}
  585. constructor TaaStack.Create;
  586. begin
  587.   inherited Create;
  588.   {allocate a head node}
  589.   FHead := snmAllocNode;
  590.   FHead^.sllnNext := nil;
  591.   FHead^.sllnData := nil;
  592. end;
  593. {--------}
  594. destructor TaaStack.Destroy;
  595. begin
  596.   Clear;
  597.   snmFreeNode(FHead);
  598.   inherited Destroy;
  599. end;
  600. {--------}
  601. procedure TaaStack.Clear;
  602. var
  603.   Temp : PsllNode;
  604. begin
  605.   Temp := FHead^.sllnNext;
  606.   while (Temp <> nil) do begin
  607.     FHead^.sllnNext := Temp^.sllnNext;
  608.     snmFreeNode(Temp);
  609.     Temp := FHead^.sllnNext;
  610.   end;
  611.   FCount := 0;
  612. end;
  613. {--------}
  614. function TaaStack.Examine : pointer;
  615. begin
  616.   if (Count = 0) then
  617.     raise Exception.Create('TaaStack.Examine: stack is empty');
  618.   Result := FHead^.sllnNext^.sllnData;
  619. end;
  620. {--------}
  621. function TaaStack.IsEmpty : boolean;
  622. begin
  623.   Result := Count = 0;
  624. end;
  625. {--------}
  626. function TaaStack.Pop : pointer;
  627. var
  628.   Temp : PsllNode;
  629. begin
  630.   if (Count = 0) then
  631.     raise Exception.Create('TaaStack.Pop: stack is empty');
  632.   Temp := FHead^.sllnNext;
  633.   Result := Temp^.sllnData;
  634.   FHead^.sllnNext := Temp^.sllnNext;
  635.   snmFreeNode(Temp);
  636.   dec(FCount);
  637. end;
  638. {--------}
  639. procedure TaaStack.Push(aItem : pointer);
  640. var
  641.   Temp : PsllNode;
  642. begin
  643.   Temp := snmAllocNode;
  644.   Temp^.sllnData := aItem;
  645.   Temp^.sllnNext := FHead^.sllnNext;
  646.   FHead^.sllnNext := Temp;
  647.   inc(FCount);
  648. end;
  649. {====================================================================}
  650.  
  651.  
  652. {===TaaQueue=========================================================}
  653. constructor TaaQueue.Create;
  654. begin
  655.   inherited Create;
  656.   {allocate a head node}
  657.   FHead := snmAllocNode;
  658.   FHead^.sllnNext := nil;
  659.   FHead^.sllnData := nil;
  660.   {make the tail pointer point to the head node}
  661.   FTail := FHead;
  662. end;
  663. {--------}
  664. destructor TaaQueue.Destroy;
  665. begin
  666.   Clear;
  667.   snmFreeNode(FHead);
  668.   inherited Destroy;
  669. end;
  670. {--------}
  671. procedure TaaQueue.Clear;
  672. var
  673.   Temp : PsllNode;
  674. begin
  675.   Temp := FHead^.sllnNext;
  676.   while (Temp <> nil) do begin
  677.     FHead^.sllnNext := Temp^.sllnNext;
  678.     snmFreeNode(Temp);
  679.     Temp := FHead^.sllnNext;
  680.   end;
  681.   FCount := 0;
  682.   {the queue is now empty so make the tail pointer point to the head
  683.    node}
  684.   FTail := FHead;
  685. end;
  686. {--------}
  687. function TaaQueue.Examine : pointer;
  688. begin
  689.   if (Count = 0) then
  690.     raise Exception.Create('TaaQueue.Examine: queue is empty');
  691.   Result := FHead^.sllnNext^.sllnData;
  692. end;
  693. {--------}
  694. function TaaQueue.IsEmpty : boolean;
  695. begin
  696.   Result := Count = 0;
  697. end;
  698. {--------}
  699. function TaaQueue.Dequeue : pointer;
  700. var
  701.   Temp : PsllNode;
  702. begin
  703.   if (Count = 0) then
  704.     raise Exception.Create('TaaQueue.Dequeue: queue is empty');
  705.   Temp := FHead^.sllnNext;
  706.   Result := Temp^.sllnData;
  707.   FHead^.sllnNext := Temp^.sllnNext;
  708.   snmFreeNode(Temp);
  709.   dec(FCount);
  710.   {if we've managed to empty the queue, the tail pointer is now
  711.    invalid, so reset it to point to the head node}
  712.   if (Count = 0) then
  713.     FTail := FHead;
  714. end;
  715. {--------}
  716. procedure TaaQueue.Enqueue(aItem : pointer);
  717. var
  718.   Temp : PsllNode;
  719. begin
  720.   Temp := snmAllocNode;
  721.   Temp^.sllnData := aItem;
  722.   Temp^.sllnNext := nil;
  723.   {add the new node to the tail of the list and make sure the tail
  724.    pointer points to the newly added node}
  725.   FTail^.sllnNext := Temp;
  726.   FTail := Temp;
  727.   inc(FCount);
  728. end;
  729. {====================================================================}
  730.  
  731.  
  732. procedure FinalizeUnit;
  733. var
  734.   STemp : PsnmPage;
  735.   DTemp : PdnmPage;
  736. begin
  737.   {destroy all the single node pages}
  738.   STemp := snmPageList;
  739.   while (STemp <> nil) do begin
  740.     snmPageList := STemp^.snmpNext;
  741.     Dispose(STemp);
  742.     STemp := snmPageList;
  743.   end;
  744.   {destroy all the double node pages}
  745.   DTemp := dnmPageList;
  746.   while (DTemp <> nil) do begin
  747.     dnmPageList := DTemp^.dnmpNext;
  748.     Dispose(DTemp);
  749.     DTemp := dnmPageList;
  750.   end;
  751. end;
  752.  
  753. initialization
  754.   snmFreeList := nil;
  755.   snmPageList := nil;
  756.   dnmFreeList := nil;
  757.   dnmPageList := nil;
  758.  
  759. finalization
  760.   FinalizeUnit;
  761.  
  762. end.
  763.